#include <cstddef>
#include <iostream>
#include <memory>

#include <boost/asio/awaitable.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio.hpp>

using TCP = boost::asio::ip::tcp;

//处理连接请求的协程函数
boost::asio::awaitable<void> echo(TCP::socket socket) {
    try
    {
        char data[1024];
        while(true)
        {
            std::size_t len = co_await socket.async_read_some(boost::asio::buffer(data), boost::asio::use_awaitable);            
            std::cout << "Received: " << len << std::endl;
            std::cout << "data: "  << data << std::endl;
            co_await boost::asio::async_write(socket, boost::asio::buffer(data, len), boost::asio::use_awaitable);
        }
    }
    catch (const std::exception& e)
    {
        std::cout << "echo Exception: " << e.what() << std::endl;
    }
}

boost::asio::awaitable<void> listener() {
    //异步获取携程调度器
    auto executor = co_await boost::asio::this_coro::executor;
    TCP::acceptor acceptor(executor, TCP::endpoint(boost::asio::ip::tcp::v4(), 12345));
    while(true)
    {   
        //async_accept: 异步接受连接请求
        //boost::asio::use_awaitable: 允许协程等待异步操作完成，并自动恢复执行
        TCP::socket s = co_await acceptor.async_accept(boost::asio::use_awaitable);

        std::cout << "Accepted connection" << std::endl;
        std::cout << "ip: " << s.remote_endpoint().address() << std::endl;

        //启动一个新的协程 但不等待其完成
        boost::asio::co_spawn(executor, echo(std::move(s)), boost::asio::detached);
    }
}

int main() {
    try
    {
        boost::asio::io_context io;
        boost::asio::signal_set signals(io, SIGINT, SIGTERM);
        signals.async_wait([&io](auto, auto){
            io.stop();
        });
        
        //启动协程 但不等待其完成
        boost::asio::co_spawn(io, listener(), boost::asio::detached);

        io.run();
    }
    catch (const std::exception& e)
    {
        std::cerr << "main Exception: " << e.what() << "\n";
    }
}





/*
启动一个新的协程
boost::asio::co_spawn(executor, awaitable, completion_token);

executor：
    类型：携程调度器 通常是 boost::asio::io_context 或其他 Asio 执行器类型
    作用：指定在哪个执行上下文中运行协程
awaitable：
    类型：一个可等待对象，通常是一个返回 boost::asio::awaitable<T> 的协程函数
    作用：这是要启动的实际协程函数
completion_token：
    类型：可以是多种类型，如 boost::asio::detached、boost::asio::use_future 等
    boost::asio::detached 的作用：
        它告诉 Asio 不需要等待这个协程完成
        如果协程抛出异常，异常会被捕获并忽略
        这对于创建"发射后不管"的后台任务很有用
    boost::asio::use_future：
        返回一个 std::future，允许稍后获取结果或异常自定义的完成处理函数
*/

/*
co_await 是 C++20 引入的协程关键字，在 Boost.Asio 的协程实现中也被广泛使用。它的作用非常重要，是实现协程异步操作的核心。
基本功能：
    co_await 用于暂停当前协程的执行，等待一个异步操作完成。
    当异步操作完成时，协程会在 co_await 的位置恢复执行。
工作原理：
    当遇到 co_await 时，协程会检查等待的对象是否已经就绪。
    如果未就绪，协程会暂停执行，并将控制权返回给调用者。
    当异步操作完成时，协程会在 co_await 的位置恢复执行。
size_t n = co_await socket.async_read_some(boost::asio::buffer(buf.get(), 1024), boost::asio::use_awaitable);
    这行代码的含义是：
    启动一个异步读取操作。
    暂停协程执行，等待读取完成。
    当读取完成时，协程恢复执行，n 被赋值为读取的字节数。
非阻塞特性：
    虽然代码看起来像是同步的，但 co_await 不会阻塞线程。
    当协程暂停时，执行器可以运行其他任务或协程。
与 co_yield 和 co_return 的区别：
    co_yield 用于生成器函数，暂时暂停并产生一个值。
    co_return 用于结束协程并可能返回一个最终值。
    co_await 专门用于等待异步操作。
*/


/*
size_t n = co_await socket.async_read_some(boost::asio::buffer(buf.get(), 1024), boost::asio::use_awaitable);

1. 异步操作的启动：
   - 当执行到这行代码时，`async_read_some` 函数会启动一个异步读取操作。
   - 这个操作被添加到操作系统的 I/O 队列中，但不会阻塞当前线程。

2. 协程的暂停：
   - `co_await` 表达式评估 `async_read_some` 的结果（一个 awaitable 对象）。
   - 如果读取没有立即完成，协程会暂停执行。
   - 协程的状态（包括局部变量）被保存。

3. 控制权的让出：
   - 协程暂停后，控制权返回到 Boost.Asio 的事件循环（通常是 `io_context::run()`）。
   - 这允许程序继续处理其他任务或协程。

4. 后台 I/O 处理：
   - 操作系统在后台继续处理 I/O 请求。
   - 这个过程是非阻塞的，不会占用程序的主线程。

5. 完成通知：
   - 当读取操作完成时（可能是几毫秒后，也可能是几秒后），操作系统通知 Boost.Asio。
   - 这通常通过操作系统的 I/O 完成机制实现（如 Linux 的 epoll 或 Windows 的 IOCP）。

6. 事件循环处理：
   - Boost.Asio 的事件循环检测到 I/O 操作完成。
   - 它找到与这个操作相关联的回调或协程。

7. 协程的恢复：
   - Asio 调度器安排恢复暂停的协程。
   - 协程的状态被恢复，执行从 `co_await` 表达式之后继续。

8. 结果处理：
   - 读取的结果（字节数或错误信息）被传递给协程。
   - 在你的代码中，这个结果被赋值给变量 `n`。

9. `boost::asio::use_awaitable` 的作用：
   - 这个参数告诉 Asio 使用协程感知的完成处理方式。
   - 它确保异步操作的结果可以通过 `co_await` 正确地返回给协程。

10. 底层实现：
    - Boost.Asio 使用了复杂的模板元编程技术来实现这种机制。
    - 它创建了一个自定义的 awaitable 对象，该对象知道如何暂停和恢复协程。

这个机制的优点是：
- 它允许编写看似同步的代码来处理异步操作。
- 在等待 I/O 时不会阻塞线程，允许高效处理大量并发连接。
- 简化了错误处理和资源管理。

`co_await` 和 Boost.Asio 的协程实现提供了一个强大的抽象层，隐藏了复杂的异步 I/O 细节，同时保持了高效的非阻塞执行模型。这使得编写高性能的网络应用变得更加直观和简单。

*/